package com.liuya.db.sql;

import java.lang.reflect.Method;
import java.util.Map;

import com.liuya.safe.exception.AuthException;
import com.liuya.safe.model.SafeUser;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.liuya.db.MapStorgeObject;

/**
 * HintSQL语句
 */
public class HintValue implements Value, java.io.Serializable {
	private static Log log = LogFactory.getLog(HintValue.class);
	private String hint;
	private String key;
	private boolean behindLike;
	private Method getter;

	public boolean isBehindLike() {
		return behindLike;
	}

	public void setBehindLike(boolean behindLike) {
		this.behindLike = behindLike;
	}

	public String toSQL() {
		return " ? ";
	}

	public String getHint() {
		return hint;
	}

	public void setHint(String hint) {
		this.hint = hint;
	}

	public String getKey() {
		return key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public Object getValue(SafeUser user, Map context) {
		if (!context.containsKey(hint)) {
			String msg = "No business data object '" + hint + "' found.";
			log.error(msg);
			throw new AuthException(msg);
		}
		Object hintObj = context.get(hint);
		if (hintObj instanceof MapStorgeObject) {
			if (!((MapStorgeObject) hintObj).containsKey(key)) {
				String msg = "No '" + key + "' found in business data object '" + hint + "'.";
				log.error(msg);
				throw new AuthException(msg);
			}
			return ((MapStorgeObject) hintObj).get(key);
		} else {
			// java bean
			try {
				if (getter == null) {
					initGetterMethod(hintObj);
				}
				return getter.invoke(hintObj, new Object[] {});
			} catch (Exception e) {
				log.error("", e);
				throw new AuthException(e);
			}
		}
	}

	private void initGetterMethod(Object o) throws Exception {
		Class clas = o.getClass();

		// try getField method first
		String getterStr = "get" + key.substring(0, 1).toUpperCase() + key.substring(1);
		try {
			getter = clas.getMethod(getterStr, new Class[] {});
		} catch (NoSuchMethodException e) {
			String isStr = "is" + key.substring(0, 1).toUpperCase() + key.substring(1);
			try {
				// try isField method
				getter = clas.getMethod(isStr, new Class[] {});
			} catch (NoSuchMethodException e1) {
				String msg = getterStr + " or " + isStr + " method not found in class:" + clas;
				log.error(msg);
				throw new AuthException(msg);
			}
		}
	}
}
